/*构造者模式*/

#include <iostream>
#include <string>
#include <memory>

//抽象产品类
class computer
{
public:
    using ptr = std::shared_ptr<computer>;

    void setBoard(const std::string& board)
    {
        _board = board;
    }

    void setDisplay(const std::string& display)
    {
        _display = display;
    }

    virtual void setOs() = 0;

    void show() {
        std::string computer = "Computer:\n{\n";
        computer += "\tboard = " + _board + ",\n"; 
        computer += "\tdisplay = " + _display + ",\n"; 
        computer += "\tOs = " + _os + ",\n"; 
        computer += "}\n";
        std::cout << computer << std::endl;
    }

protected:
    std::string _board;
    std::string _display;
    std::string _os;
};


//具体产品类
class MyComputer : public computer
{
public:
    using ptr = std::shared_ptr<MyComputer>;

    virtual void setOs() override
    {
        _os = "Max Os X12";
    }
};


//抽象建造者类
class Builder
{
public:
    using ptr = std::shared_ptr<Builder>;

    virtual void buildBoard(const std::string& board) = 0;
    virtual void buildDisplay(const std::string& display) = 0;
    virtual void buildOs() = 0;
    virtual computer::ptr build() = 0;
};


//具体建造者类
class MyBuilder : public Builder
{
public:
    using ptr = std::shared_ptr<MyBuilder>;   

    MyBuilder()
        :_computer(new MyComputer)
    {}

    virtual void buildBoard(const std::string& board) override
    {
        _computer->setBoard(board);
    }
    virtual void buildDisplay(const std::string& display) override
    {
        _computer->setDisplay(display);
    }
    virtual void buildOs() override
    {
        _computer->setOs();
    }

    virtual computer::ptr build() override
    {
        return _computer;
    }
protected:
    computer::ptr _computer;
};


//指挥者类
class Director
{
public:
    Director(Builder::ptr builder)
        :_builder(builder)
    {}

    computer::ptr construct(const std::string& board, const std::string& display)
    {
        _builder->buildBoard(board);
        _builder->buildDisplay(display);
        _builder->buildOs();
        return _builder->build();
    }

private:
    Builder::ptr _builder;
};


int main()
{
    Builder::ptr buil(new MyBuilder());
    std::shared_ptr<Director> dir(new Director(buil));
    dir->construct("英特尔主板", "VOC显示器");
    computer::ptr com = buil->build();
    com->show();


    return 0;
}